package controller

import (
	"fmt"
	"time"

	"commonUtils/app"
	"commonUtils/utils"
)

const (
	OK       = 20000
	ERROR    = 50000
	AUTHFAIL = 50008
)

// 权限检查
func CheckApiAuth(c *Context, key string) (string, int) {
	var data, crc string
	var ok bool

	if c.Method() == "POST" {
		var dataIntfc = c.GetPostData("data")
		if nil == dataIntfc {
			return "param data not exist", ERROR + 1
		}
		if data, ok = dataIntfc.(string); !ok || data == "" {
			var datas []string
			if datas, ok = dataIntfc.([]string); !ok || len(datas) == 0 {
				return "param data parse failed", ERROR + 1
			}
			data = datas[0]
			if "" == data {
				return "param data not exist1", ERROR + 1
			}
		}
	} else if c.Method() == "GET" {
		data = c.GetData("data")
		if "" == data {
			return "param data not exist1", ERROR + 1
		}
	} else {
		return "Method error", ERROR + 1
	}
	// utils.Debug("data : %s", data)
	data, err := utils.ApiUrlDecode(data)
	if err != nil {
		return "param data error", ERROR + 2
	}

	if crc = c.GetHeader(utils.CRC_VERIFY_KEY); crc == "" {
		return "param error", ERROR + 2
	}

	crc, aesType, err := parseCRC(crc)
	if err != nil {
		return "verify error : " + err.Error(), ERROR + 2
	}

	countCrc := fmt.Sprintf("%v", utils.CRC32(data))
	if countCrc != crc {
		utils.Debug("auth check data : %s, crc : %v,dest crc : %v , dest type : %v", data, countCrc, crc, aesType)
		return "verify error ", ERROR + 3 //  + countCrc + " : " + crc
	}

	decode, err := utils.AesDecode(data, key, aesType)

	if err != nil {
		return "encode error", ERROR + 4
	}
	bodyData, err := utils.JsonToMap(decode)
	if err != nil {
		return "parse error : " + err.Error(), ERROR + 5
	}

	if t, ok := bodyData["time"]; ok {
		intt := utils.ToInt64(t)
		ti := utils.SecToTime(intt)
		var span = time.Now().Sub(ti)
		if span < -5*time.Minute || span > 5*time.Minute {
			utils.Debug("time : %v , now : %v , span : %v", t, time.Now(), span)
			return "time out of range", ERROR + 6
		}
	} else {
		return "time error", ERROR + 6
	}
	// delete(bodyData, "time")
	c.SetBodyData(bodyData)

	return "", OK
}

var idSplit = "&*&"

func GetWsConnID(c *Context) string {
	token := c.SessionID()
	return fmt.Sprintf("%v%s%v", c.GetPostData("url").(string), idSplit, token)
}

func GetAddrByWsConnID(c string) string {
	arr := utils.Split(c, idSplit)
	return arr[0]
}

func parseCRC(crc string) (string, utils.AESType, error) {
	ret := crc[:len(crc)-1]
	t := crc[len(crc)-1:]
	// utils.Debug("crc : %s , ret : %s , t : %s", crc, ret, t)
	at, err := utils.StringToInt(t)
	return ret, utils.AESType(at), err
}

func AppBaseCheck(c *Context) (string, int) {
	utils.Debug("header : %+v", c.R.Header)
	if "" == c.GetHeader("deviceId") || "" == c.GetHeader("model") || "" == c.GetHeader("platform") {
		return "", ERROR
	}

	c.ClientData = &app.ClientInfo{
		DeviceId: c.GetHeader("deviceId"),
		Model:    c.GetHeader("model"),
		Platform: c.GetHeader("platform"),
	}

	return "", OK
}

func AppWsCheck(c *Context) (string, int) {
	auth := c.GetData("auth")
	if "" == auth {
		return "auth failed", ERROR
	}
	auth, err := utils.ApiUrlDecode(auth)
	if err != nil {
		return err.Error(), ERROR
	}
	utils.Debug("auth data : %s", auth)

	data, err := utils.Base64Manager().Decode(auth)
	if err != nil {
		utils.Debug("encoder : %s", utils.Base64Manager().GetEncoder())
		utils.Error("Base64 Decode error : %s", err)
		return "auth failed!", ERROR
	}

	utils.Debug("AppWsCheck data : %s", data)

	var param *app.AppWsParam
	err = utils.JsonToStruct(data, &param)
	if err != nil {
		utils.Error("ClientInfo get faild : %s", err)
		return "auth failed !", ERROR
	}

	validator := utils.GetValidate()

	if err = validator.Struct(param); err != nil {
		utils.Error("clientInfo validate error : %s", err)
		return "param error !", ERROR
	}

	c.ClientData = param.GetClientInfo()

	c.R.Header["Authorization"] = []string{param.Authorization}

	return "", OK
}
